home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / read-ical.c < prev    next >
C/C++ Source or Header  |  1997-08-08  |  8KB  |  325 lines

  1. /* read-ical.c:  Translate Pilot ToDo and Datebook databases into ical 2.0 format
  2.  *
  3.  * Copyright (c) 1996, Kenneth Albanowski
  4.  *
  5.  * This is free software, licensed under the GNU Public License V2.
  6.  * See the file COPYING for details.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "pi-source.h"
  13. #include "pi-socket.h"
  14. #include "pi-todo.h"
  15. #include "pi-datebook.h"
  16. #include "pi-dlp.h"
  17.  
  18. char * tclquote(char * in)
  19. {
  20.   static char * buffer = 0;
  21.   char * out;
  22.   char * pos;
  23.   int len;
  24.   
  25.   /* Skip leading bullet (and any whitespace after) */
  26.   if (in[0] == '\x95') {
  27.     ++in;
  28.     while(in[0] == ' ' || in[0] == '\t') {
  29.     ++in;
  30.     }
  31.   }
  32.  
  33.   len = 3;
  34.   pos = in;
  35.   while(*pos) {
  36.     if((*pos == '\\') || (*pos == '"') || (*pos == '[') || (*pos == '{') || (*pos == '$'))
  37.       len++;
  38.     len++;
  39.     pos++;
  40.   }
  41.   
  42.   if (buffer)
  43.     free(buffer);
  44.   buffer = (char*)malloc(len);
  45.   out = buffer;
  46.  
  47.   pos = in;
  48.   *out++ = '"';
  49.   while(*pos) {
  50.     if((*pos == '\\') || (*pos == '"') || (*pos == '[') || (*pos == '{') || (*pos == '$'))
  51.       *out++ = '\\';
  52.     *out++=*pos++;
  53.   }
  54.   *out++ = '"';
  55.   *out++ = '\0';
  56.   
  57.   return buffer;
  58. }
  59.  
  60. static void Usage(char *progname)
  61. {
  62.     fprintf(stderr,"Usage: %s [-d] [-p pubtext] [%s] calfile\n"
  63.         "Note: calfile will be overwritten!\n"
  64.         "   -d         : Datebook only, no Todos\n"
  65.         "   -p pubtext : Replace text of items not starting with a bullet "
  66.         "with pubtext\n",
  67.     progname, TTYPrompt);
  68.     exit(2);
  69. }
  70.  
  71. int main(int argc, char *argv[])
  72. {
  73.   struct pi_sockaddr addr;
  74.   int db;
  75.   int sd;
  76.   int i;
  77.   FILE *ical;
  78.   struct PilotUser U;
  79.   int ret;
  80.   unsigned char buffer[0xffff];
  81.   char cmd[128];
  82.   struct ToDoAppInfo tai;
  83.   int read_todos = 1;
  84.   char *pubtext = NULL;
  85.   char *progname = argv[0];
  86.   char *port = getenv("PILOTPORT");
  87.  
  88.   if (!port) port = "/dev/pilot";
  89.  
  90.   while (argc > 1 && argv[1][0] == '-') {
  91.     if (!strcmp(argv[1], "-d")) {
  92.     /* Datebook only */
  93.     read_todos = 0;
  94.     } else if (!strcmp(argv[1], "-p")) {
  95.     /* Public only, text supplied */
  96.     if (argv[2] == NULL) {
  97.         Usage(progname);
  98.     }
  99.     pubtext = argv[2];
  100.     --argc; ++argv;
  101.     } else {
  102.     Usage(progname);
  103.     }
  104.     --argc; ++argv;
  105.   }
  106.  
  107.   if (argc != 2 && argc != 3) {
  108.     Usage(progname);
  109.   }
  110.   if (argc == 3) {
  111.     port = argv[1];
  112.     --argc; ++argv;
  113.   }
  114.   if (!(sd = pi_socket(PI_AF_SLP, PI_SOCK_STREAM, PI_PF_PADP))) {
  115.     perror("pi_socket");
  116.     exit(1);
  117.   }
  118.     
  119.   addr.pi_family = PI_AF_SLP;
  120.   strcpy(addr.pi_device,port);
  121.   
  122.   ret = pi_bind(sd, (struct sockaddr*)&addr, sizeof(addr));
  123.   if(ret == -1) {
  124.     perror("pi_bind");
  125.     exit(1);
  126.   }
  127.  
  128.   ret = pi_listen(sd,1);
  129.   if(ret == -1) {
  130.     perror("pi_listen");
  131.     exit(1);
  132.   }
  133.  
  134.   sd = pi_accept(sd, 0, 0);
  135.   if(sd == -1) {
  136.     perror("pi_accept");
  137.     exit(1);
  138.   }
  139.  
  140.   /* Ask the pilot who it is. */
  141.   dlp_ReadUserInfo(sd,&U);
  142.   
  143.   /* Tell user (via Pilot) that we are starting things up */
  144.   dlp_OpenConduit(sd);
  145.   
  146.   unlink(argv[1]);
  147.   sprintf(cmd, "ical -f - -calendar %s", argv[1]);
  148.   ical = popen(cmd, "w");
  149.   
  150.   fprintf(ical,"calendar cal $ical(calendar)\n");
  151.   
  152.   if (read_todos) {
  153.   /* Open the ToDo database, store access handle in db */
  154.   if(dlp_OpenDB(sd, 0, 0x80|0x40, "ToDoDB", &db) < 0) {
  155.     puts("Unable to open ToDoDB");
  156.     dlp_AddSyncLogEntry(sd, "Unable to open ToDoDB.\n");
  157.     exit(1);
  158.   }
  159.   
  160.   dlp_ReadAppBlock(sd, db, 0, buffer, 0xffff);
  161.   unpack_ToDoAppInfo(&tai, buffer, 0xffff);
  162.   
  163.   for (i=0;1;i++) {
  164.       struct ToDo t;
  165.       int attr, category;
  166.       recordid_t id;
  167.       char id_buf[255];
  168.                                  
  169.       int len = dlp_ReadRecordByIndex(sd, db, i, buffer, &id, 0, &attr, &category);
  170.       if(len<0)
  171.           break;
  172.           
  173.       /* Skip deleted records */
  174.       if((attr & dlpRecAttrDeleted) || (attr & dlpRecAttrArchived))
  175.           continue;
  176.           
  177.     unpack_ToDo(&t, buffer, len);
  178.     
  179.     fprintf(ical,"set n [notice]\n");
  180.     /* '\x95' is the "bullet" character */
  181.     fprintf(ical,"$n text %s\n", tclquote((pubtext &&
  182.         t.description[0] != '\x95') ? pubtext : t.description));
  183.     fprintf(ical,"$n date [date today]\n");
  184.     fprintf(ical,"$n todo 1\n");
  185.     fprintf(ical,"$n option Priority %d\n", t.priority);
  186.         sprintf(id_buf, "%lx", id);
  187.         fprintf(ical,"$n option PilotRecordId %s\n", id_buf);
  188.     fprintf(ical,"$n done %d\n", t.complete ? 1 : 0);
  189.     fprintf(ical,"cal add $n\n");
  190.     
  191.     free_ToDo(&t);
  192.   }
  193.  
  194.   /* Close the database */
  195.   dlp_CloseDB(sd, db);
  196.  
  197.   dlp_AddSyncLogEntry(sd, "Read todos from Pilot.\n");
  198.   }
  199.  
  200.   /* Open the Datebook's database, store access handle in db */
  201.   if(dlp_OpenDB(sd, 0, 0x80|0x40, "DatebookDB", &db) < 0) {
  202.     puts("Unable to open DatebookDB");
  203.     dlp_AddSyncLogEntry(sd, "Unable to open DatebookDB.\n");
  204.     pi_close(sd);
  205.     exit(1);
  206.   }
  207.   
  208.   
  209.  
  210.   for (i=0;1;i++) {
  211.       int j;
  212.       struct Appointment a;
  213.       int attr;
  214.       recordid_t id;
  215.       char id_buf[255];
  216.                                  
  217.       int len = dlp_ReadRecordByIndex(sd, db, i, buffer, &id, 0, &attr, 0);
  218.       if(len<0)
  219.           break;
  220.           
  221.       /* Skip deleted records */
  222.       if((attr & dlpRecAttrDeleted) || (attr & dlpRecAttrArchived))
  223.           continue;
  224.           
  225.     unpack_Appointment(&a, buffer, len);
  226.     
  227.     if (a.event) {
  228.       fprintf(ical,"set i [notice]\n");
  229.  
  230.     } else {
  231.       int start,end;
  232.  
  233.       fprintf(ical,"set i [appointment]\n");
  234.       
  235.       start = a.begin.tm_hour*60 + a.begin.tm_min;
  236.       end   = a.end.tm_hour*60 + a.end.tm_min;
  237.  
  238.       fprintf(ical,"$i starttime %d\n", start);
  239.       fprintf(ical,"$i length %d\n", end-start);
  240.     }
  241.     
  242.     /* '\x95' is the "bullet" character */
  243.     fprintf(ical,"$i text %s\n", tclquote((pubtext &&
  244.         a.description[0] != '\x95') ? pubtext : a.description));
  245.     
  246.     fprintf(ical,"set begin [date make %d %d %d]\n", a.begin.tm_mday,a.begin.tm_mon+1,a.begin.tm_year+1900);
  247.     
  248.     if (a.repeatFrequency) {
  249.       if (a.repeatType == repeatDaily) {
  250.         fprintf(ical,"$i dayrepeat %d $begin\n", a.repeatFrequency);
  251.       } else if(a.repeatType == repeatMonthlyByDate) {
  252.         fprintf(ical,"$i month_day %d $begin %d\n",a.begin.tm_mon+1,a.repeatFrequency);
  253.       } else if(a.repeatType == repeatMonthlyByDay) {
  254.         if (a.repeatDay>=domLastSun) {
  255.           fprintf(ical,"$i month_last_week_day %d 1 $begin %d\n", a.repeatDay % 7 + 1,
  256.                                                         a.repeatFrequency);
  257.         } else {
  258.           fprintf(ical,"$i month_week_day %d %d $begin %d\n", a.repeatDay % 7 + 1,
  259.                                                         a.repeatDay / 7 + 1,
  260.                                                         a.repeatFrequency);
  261.         }
  262.       } else if(a.repeatType == repeatWeekly) {
  263.         /*
  264.          * Handle the case where the user said weekly repeat, but
  265.          * really meant daily repeat every n*7 days.  Note: We can't
  266.          * do days of the week and a repeat-frequency > 1, so do the
  267.          * best we can and go on.
  268.          */
  269.         if (a.repeatFrequency > 1) {
  270.         int ii, found;
  271.         for (ii = 0, found = 0; ii < 7; ii++) {
  272.             if (a.repeatDays[i])
  273.             found++;
  274.         }
  275.         if (found > 1)
  276.             fprintf(stderr, "Incomplete translation of %s\n",
  277.                 a.description);
  278.         fprintf(ical,"$i dayrepeat %d $begin\n", a.repeatFrequency * 7);
  279.         } else {
  280.         fprintf(ical,"$i weekdays ");
  281.         for (i=0;i<7;i++)
  282.           if (a.repeatDays[i])
  283.             fprintf(ical,"%d ", i+1);
  284.         fprintf(ical,"\n");
  285.         }
  286.       } else if(a.repeatType == repeatYearly) {
  287.         fprintf(ical,"$i monthrepeat %d $begin\n", 12 * a.repeatFrequency);
  288.       }
  289.       fprintf(ical,"$i start $begin\n");
  290.       if (!a.repeatForever)
  291.         fprintf(ical,"$i finish [date make %d %d %d]\n", a.repeatEnd.tm_mday, a.repeatEnd.tm_mon+1, 
  292.                                                    a.repeatEnd.tm_year+1900);
  293.       if (a.exceptions)
  294.         for (j=0;j<a.exceptions;j++)
  295.           fprintf(ical,"$i deleteon [date make %d %d %d]\n", a.exception[j].tm_mday,
  296.                                                        a.exception[j].tm_mon+1,
  297.                                                        a.exception[j].tm_year+1900);
  298.     } else 
  299.           fprintf(ical,"$i date $begin\n");
  300.     
  301.         sprintf(id_buf, "%lx", id);
  302.         fprintf(ical,"$i option PilotRecordId %s\n", id_buf);
  303.         
  304.     fprintf(ical,"cal add $i\n");
  305.  
  306.     free_Appointment(&a);
  307.         
  308.   }
  309.   
  310.   fprintf(ical,"cal save [cal main]\n");
  311.   fprintf(ical,"exit\n");
  312.   
  313.   pclose(ical);
  314.  
  315.   /* Close the database */
  316.   dlp_CloseDB(sd, db);
  317.  
  318.   dlp_AddSyncLogEntry(sd, "Read datebook from Pilot.\n");
  319.  
  320.   pi_close(sd);  
  321.   
  322.   return 0;
  323. }
  324.  
  325.